﻿using System.ComponentModel.DataAnnotations.Schema;
using NUnit.Framework;
using Shouldly;

namespace Test.MySql.ColumnTypeTests
{
    [TestFixture]
    internal class ColumnTypesTestsDecimal : TestBase
    {
        #region 模型
        [Table("test")]
        public class Model
        {
            /// <summary>
            /// decimal(28,15)
            /// </summary>
            public decimal? t_decimal28_15 { get; set; }

            /// <summary>
            /// decimal(30,15)
            /// </summary>
            public decimal? t_decimal30_15 { get; set; }

            /// <summary>
            /// decimal(40,15)
            /// </summary>
            public decimal? t_decimal40_15 { get; set; }
        }
        #endregion

        [SetUp]
        public void Setup()
        {
            DropTableIfExist("test");
            db.ExecuteSql(@"
create table test.test(
	t_decimal28_15 decimal(28,15),
	t_decimal30_15 decimal(30,15),
	t_decimal40_15 decimal(40,15)
)");
            db.ExecuteSql(@"
insert into test(t_decimal28_15,t_decimal30_15,t_decimal40_15) values
	(1234567890123.123456789012345,
	123456789012345.123456789012345,
	1234567890123456789012345.123456789012345)
");
        }

        [Test]
        public void TestDefaultParse()
        {
            //mysql中 decimal 是定点小数, 精度高且不失真 但 c# 中 decimal 也是浮点数, 只是比 float/decimal 精度高,
            //所以会出现失真的情况
            var dic = db.SelectDictionary("select * from test");
            dic["t_decimal28_15"].GetType().ShouldBe(typeof(decimal));
            dic["t_decimal30_15"].GetType().ShouldBe(typeof(decimal));
            dic["t_decimal40_15"].GetType().ShouldBe(typeof(decimal));

            dic["t_decimal28_15"].ShouldBe(1234567890123.123456789012345m);
            dic["t_decimal30_15"].ShouldBe(123456789012345.12345678901235m);//失真
            dic["t_decimal40_15"].ShouldBe(1234567890123456789012345.1235m);//失真

            db.SelectDataReader(reader =>
            {
                reader.RawReader.Read();
                reader.RawReader.GetDecimal(0).ShouldBe(1234567890123.123456789012345m);
                reader.RawReader.GetDecimal(1).ShouldBe(123456789012345.12345678901235m);//失真
                reader.RawReader.GetDecimal(2).ShouldBe(1234567890123456789012345.1235m);//失真
            }, "select * from test");
        }

        [Test]
        public void TestOrmReadWrite()
        {
            //mysql中 decimal 是定点小数, 精度高且不失真 但 c# 中 decimal 也是浮点数, 只是比 float/decimal 精度高,
            //所以会出现失真的情况
            var model = new Model
            {
                t_decimal28_15 = 1234567890123.123456789012345m,
                t_decimal30_15 = 123456789012345.123456789012345m,//已经失真
                t_decimal40_15 = 1234567890123456789012345.123456789012345m,//已经失真
            };
            validate(model);

            TruncateTable("test");
            var sql = db.Insert<Model>().SetEntity(model).ToSql();
            sql.ShouldBe("insert into `test`(`t_decimal28_15`,`t_decimal30_15`,`t_decimal40_15`) values(1234567890123.123456789012345,123456789012345.12345678901234,1234567890123456789012345.1235);");
            db.Insert<Model>().SetEntity(model).ExecuteAffrows();

            model = db.SelectModel<Model>("select * from test");
            validate(model);

            void validate(Model model)
            {
                model.t_decimal28_15.ShouldBe(1234567890123.123456789012345m);
                model.t_decimal30_15.ShouldBe(123456789012345.12345678901234m);//已经失真
                model.t_decimal40_15.ShouldBe(1234567890123456789012345.1235m);//已经失真
            }
        }
    }
}
